﻿using System.Linq;
using System.Runtime;
using NUnit.Framework;

namespace Simhopp.Common
{
    class TestDatabaseCompetition
    {

        private Competition _testC;

        private Diver _testD1;
        private Diver _testD2;

        private Dive _testDive1;

        private User _testJ1;
        private User _testJ2;
        private User _testJ3;
        private User _testJ4;
        private User _testJ5;

        private Score _testScore1;
        private Score _testScore2;
        private Score _testScore3;
        private Score _testScore4;
        private Score _testScore5;

        [SetUp]
        public void Init()
        {
            MyDbConnection.SetConnectionString(
                @"Data Source=DS9;Initial Catalog=Diving;Integrated Security=True;MultipleActiveResultSets=True");

            _testC = new Competition
            {
                Name = "Örebro Open",
                City = "Örebro",
                Country = "Sweden",
                Date = "2014-05-30",
                Gender = Genders.Female,
                NumberOfJudges = 5,
                CurrentRound = Rounds.Configure,
                CurrentDiverIndex = 1,
                NotInProgress = "true"
            };

            _testC.Heights[0] = (Heights.OneMeter);
            _testC.Heights[1] = (Heights.ThreeMeters);
            _testC.Heights[2] = (Heights.TenMeters);

            _testD1 = new Diver
            {
                Name = "Karin",
                Age = 22,
                Gender = Genders.Female,
                Nationality = "Sweden",
                SocialSecurityNumber = "11"
                
            };
            _testD2 = new Diver
            {
                Name = "Jane",
                Age = 24,
                Gender = Genders.Female,
                Nationality = "Great Britain",
                SocialSecurityNumber = "22"
            };


            _testJ1 = new User
            {
                UserName = "ankan",
                Name = "Anders Andersson",
                Age = 45,
                Nationality = "Sweden",
                Gender = Genders.Male,
                AccountType = AccountTypes.Judge,
                SocialSecurityNumber = "33"
            };
            _testJ2 = new User
            {
                UserName = "lasse",
                Name = "Lars Larsson",
                Age = 42,
                Nationality = "Sweden",
                Gender = Genders.Male,
                AccountType = AccountTypes.Judge,
                SocialSecurityNumber = "33"
            };
            _testJ3 = new User
            {
                UserName = "göran",
                Name = "Göran Göransson",
                Age = 32,
                Nationality = "Sweden",
                Gender = Genders.Male,
                AccountType = AccountTypes.Judge,
                SocialSecurityNumber = "44"

            };
            _testJ4 = new User
            {
                UserName = "judy",
                Name = "Judy Judeson",
                Age = 31,
                Nationality = "England",
                Gender = Genders.Female,
                AccountType = AccountTypes.Judge,
                SocialSecurityNumber = "55"

            };
            _testJ5 = new User
            {
                UserName = "gunvor",
                Name = "Gunvor Gunvorsdotter",
                Age = 55,
                Nationality = "Sweden",
                Gender = Genders.Female,
                AccountType = AccountTypes.HeadJudge,
                SocialSecurityNumber = "66"
            };

            _testC.AddParticipant(_testD1);
            

            _testC.AddParticipant(_testD2);
            
            _testScore1 = new Score(_testJ1, 7.5);
            _testScore2 = new Score(_testJ2, 3.5);
            _testScore3 = new Score(_testJ3, 4.5);
            _testScore4 = new Score(_testJ4, 6.0);
            _testScore5 = new Score(_testJ5, 9.0);


            _testDive1 = new Dive
            {
                Id = 14,
                TotalScore = 23.5f,
                DiveType = new DivingType
                {
                    ID = "001C",
                    DifficultyFactor = 1.00,
                    Height = Heights.TenMeters,
                    KeyId = 12,
                    TypeName = "Forward Entry Tuck"
                }
            };
            _testD1.Dives[0] = _testDive1;

            _testD1.Dives[0].KeyId = 14;
            _testD1.Dives[1].KeyId = 1;
            _testD1.Dives[2].KeyId = 23;
            _testD2.Dives[0].KeyId = 24;
            _testD2.Dives[1].KeyId = 55;

            _testD1.Dives[0].AddScore(_testScore1);
            _testD1.Dives[1].AddScore(_testScore2);
            _testD1.Dives[2].AddScore(_testScore3);
            _testD2.Dives[0].AddScore(_testScore4);
            _testD2.Dives[1].AddScore(_testScore5);

            _testC.AddJudge(_testJ1);
            _testC.AddJudge(_testJ2);
            _testC.AddJudge(_testJ3);
            _testC.AddJudge(_testJ4);
            _testC.AddJudge(_testJ5);

            CompetitionMap.SaveCompetitionToDatabase(_testC);
        }

        [Test]
        public void TestReadCompetition()
        {
            var tmpCompetition = ReadCompetition.ReadCompetitionById(_testC.Id);
            CompareCompetitions(tmpCompetition, _testC);

            CompareJudges(tmpCompetition.Judges[0], _testJ1);
            CompareJudges(tmpCompetition.Judges[1], _testJ2);
            CompareJudges(tmpCompetition.Judges[2], _testJ3);
            CompareJudges(tmpCompetition.Judges[3], _testJ4);
            CompareJudges(tmpCompetition.Judges[4], _testJ5);
            
            CompareDivers(tmpCompetition.Participants[0], _testD1);
            CompareDivers(tmpCompetition.Participants[1], _testD2);

            CompareDives(tmpCompetition.Participants[0].Dives[0], _testDive1);

        }


        public void CompareCompetitions(Competition c1, Competition c2)
        {
            Assert.AreEqual(c1.Id, c2.Id);
            Assert.AreEqual(c1.Name, c2.Name);
            Assert.AreEqual(c1.Date, c2.Date);
            Assert.AreEqual(c1.NumberOfJudges, c2.NumberOfJudges);
            Assert.AreEqual(c1.City, c2.City);
            Assert.AreEqual(c1.Country, c2.Country);
            Assert.AreEqual(c1.Gender, c2.Gender);
            Assert.AreEqual(c1.CurrentRound, c2.CurrentRound);
            Assert.AreEqual(c1.CurrentDiverIndex, c2.CurrentDiverIndex);
            Assert.AreEqual(c1.NotInProgress, c2.NotInProgress);
            Assert.AreEqual(c1.Heights, c2.Heights);

        }

        public void CompareJudges(User u1, User u2)
        {
            Assert.AreEqual(u1.Id, u2.Id);
            Assert.AreEqual(u1.Name, u2.Name);
            Assert.AreEqual(u1.Age, u2.Age);
            Assert.AreEqual(u1.Gender, u2.Gender);
            Assert.AreEqual(u1.Nationality, u2.Nationality);
            Assert.AreEqual(u1.SocialSecurityNumber, u2.SocialSecurityNumber);
            Assert.AreEqual(u1.UserName, u2.UserName);
            Assert.AreEqual(u1.CompetitionId, u2.CompetitionId);
        }

        public void CompareDivers(Diver d1, Diver d2)
        {
            Assert.AreEqual(d1.Id, d2.Id);
            Assert.AreEqual(d1.Name, d2.Name);
            Assert.AreEqual(d1.Age, d2.Age);
            Assert.AreEqual(d1.Gender, d2.Gender);
            Assert.AreEqual(d1.Nationality, d2.Nationality);
            Assert.AreEqual(d1.SocialSecurityNumber, d2.SocialSecurityNumber);
            Assert.AreEqual(d1.CompetitionId, d2.CompetitionId);
        }

        public void CompareDives(Dive d1, Dive d2)
        {
            Assert.AreEqual(d1.Id, d2.Id);
            Assert.AreEqual(d1.DiveType, d2.DiveType);
            Assert.AreEqual(d1.TotalScore, d2.TotalScore);
        }

        public Competition GetCompetitionById(int id)
        {
            var allCompetitions = CompetitionMap.ReadAllCompetitionsFromDatabase();
            var allCredentials = CredentialsMap.ReadAllCredentialsFromDataBase();
            var allDivers = DiverMap.ReadAllDiversFromDatabase();
            var allDives = DiveMap.ReadAllDivesFromDatabase();
            var allScores = ScoreMap.ReadAllScoresFromDatabase();
            var allUsers = UserMap.ReadAllUsersFromDataBase();

            foreach (var diver in allDivers)
            {
                var diver1 = diver;
                foreach (var dive in allDives.Where(dive => dive.DiverId == diver1.Id))
                    diver.AddDive(dive);
                diver.Credentials = (from credentials in allCredentials
                                     where credentials.Id == diver.CredentialsId
                                     select credentials).FirstOrDefault();
            }

            foreach (var user in from user in allUsers let user1 = user select user)
            {
                user.Credentials = (from credentials in allCredentials
                                    where credentials.Id == user.CredentialsId
                                    select credentials).FirstOrDefault();
            }

            foreach (var score in allScores)
            {
                score.Judge = (from judge in allUsers
                                      where judge.Id == score.JudgeId
                                      select judge).FirstOrDefault();
            }

            foreach (var dive in allDives)
            {
                dive.RemoveAllScores();
                var dive1 = dive;
                foreach (var score in allScores.Where(score => score.DiveId == dive1.Id))
                    dive.AddScore(score);
            }

            foreach (var competition in allCompetitions)
            {
                var competition1 = competition;
                foreach (var diver in allDivers.Where(diver => diver.CompetitionId == competition1.Id))
                    competition.AddParticipant(diver);
                foreach (var user in allUsers.Where(user => user.CompetitionId == competition1.Id))
                    competition.AddJudge(user);
            }

            return (from competition in allCompetitions
                where competition.Id == id
                select competition).FirstOrDefault();
        }

        [TearDown]
        public void Terminate()
        {
            DiverMap.RemoveDiverFromDatabase(_testD1);
            DiverMap.RemoveDiverFromDatabase(_testD2);

            UserMap.RemoveUserFromDataBase(_testJ1);
            UserMap.RemoveUserFromDataBase(_testJ2);
            UserMap.RemoveUserFromDataBase(_testJ3);
            UserMap.RemoveUserFromDataBase(_testJ4);
            UserMap.RemoveUserFromDataBase(_testJ5);

            ScoreMap.RemoveScoreFromDatabase(_testScore1);
            ScoreMap.RemoveScoreFromDatabase(_testScore2);
            ScoreMap.RemoveScoreFromDatabase(_testScore3);
            ScoreMap.RemoveScoreFromDatabase(_testScore4);
            ScoreMap.RemoveScoreFromDatabase(_testScore5);

            CompetitionMap.RemoveCompetitionFromDatabase(_testC);
        }
    }

}
